From: kfraser@localhost.localdomain Date: Fri, 31 Aug 2007 14:46:37 +0000 (+0100) Subject: Implement ia64 continuable domain destroy. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14987^2~20 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=6680dbcb4f587b38220b0f1fe0d10ef5ddd9546a;p=xen.git Implement ia64 continuable domain destroy. Signed-off-by: Isaku Yamahata --- diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 7914a81406..e9d1d3103b 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -563,6 +563,7 @@ int arch_domain_create(struct domain *d) goto fail_nomem; memset(&d->arch.mm, 0, sizeof(d->arch.mm)); + d->arch.mm_teardown_offset = 0; if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL) goto fail_nomem; @@ -938,12 +939,15 @@ static void relinquish_memory(struct domain *d, struct list_head *list) int domain_relinquish_resources(struct domain *d) { + int ret; /* Relinquish guest resources for VT-i domain. */ if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0])) vmx_relinquish_guest_resources(d); /* Tear down shadow mode stuff. */ - mm_teardown(d); + ret = mm_teardown(d); + if (ret != 0) + return ret; /* Relinquish every page of memory. */ relinquish_memory(d, &d->xenpage_list); diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 6980736063..215d0dc373 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -215,6 +215,18 @@ alloc_dom_xen_and_dom_io(void) BUG_ON(dom_io == NULL); } +static int +mm_teardown_can_skip(struct domain* d, unsigned long offset) +{ + return d->arch.mm_teardown_offset > offset; +} + +static void +mm_teardown_update_offset(struct domain* d, unsigned long offset) +{ + d->arch.mm_teardown_offset = offset; +} + static void mm_teardown_pte(struct domain* d, volatile pte_t* pte, unsigned long offset) { @@ -252,46 +264,73 @@ mm_teardown_pte(struct domain* d, volatile pte_t* pte, unsigned long offset) } } -static void +static int mm_teardown_pmd(struct domain* d, volatile pmd_t* pmd, unsigned long offset) { unsigned long i; volatile pte_t* pte = pte_offset_map(pmd, offset); for (i = 0; i < PTRS_PER_PTE; i++, pte++) { - if (!pte_present(*pte)) // acquire semantics + unsigned long cur_offset = offset + (i << PAGE_SHIFT); + if (mm_teardown_can_skip(d, cur_offset + PAGE_SIZE)) continue; - mm_teardown_pte(d, pte, offset + (i << PAGE_SHIFT)); + if (!pte_present(*pte)) { // acquire semantics + mm_teardown_update_offset(d, cur_offset); + continue; + } + mm_teardown_update_offset(d, cur_offset); + mm_teardown_pte(d, pte, cur_offset); + if (hypercall_preempt_check()) + return -EAGAIN; } + return 0; } -static void +static int mm_teardown_pud(struct domain* d, volatile pud_t *pud, unsigned long offset) { unsigned long i; volatile pmd_t *pmd = pmd_offset(pud, offset); for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { - if (!pmd_present(*pmd)) // acquire semantics + unsigned long cur_offset = offset + (i << PMD_SHIFT); + if (mm_teardown_can_skip(d, cur_offset + PMD_SIZE)) + continue; + if (!pmd_present(*pmd)) { // acquire semantics + mm_teardown_update_offset(d, cur_offset); continue; - mm_teardown_pmd(d, pmd, offset + (i << PMD_SHIFT)); + } + if (mm_teardown_pmd(d, pmd, cur_offset)) + return -EAGAIN; } + return 0; } -static void +static int mm_teardown_pgd(struct domain* d, volatile pgd_t *pgd, unsigned long offset) { unsigned long i; volatile pud_t *pud = pud_offset(pgd, offset); for (i = 0; i < PTRS_PER_PUD; i++, pud++) { - if (!pud_present(*pud)) // acquire semantics + unsigned long cur_offset = offset + (i << PUD_SHIFT); +#ifndef __PAGETABLE_PUD_FOLDED + if (mm_teardown_can_skip(d, cur_offset + PUD_SIZE)) continue; - mm_teardown_pud(d, pud, offset + (i << PUD_SHIFT)); +#endif + if (!pud_present(*pud)) { // acquire semantics +#ifndef __PAGETABLE_PUD_FOLDED + mm_teardown_update_offset(d, cur_offset); +#endif + continue; + } + if (mm_teardown_pud(d, pud, cur_offset)) + return -EAGAIN; } + return 0; } -void +int mm_teardown(struct domain* d) { struct mm_struct* mm = &d->arch.mm; diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 40bc6e52ad..3b69921f33 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -171,6 +171,9 @@ struct arch_domain { #ifdef CONFIG_XEN_IA64_TLB_TRACK struct tlb_track* tlb_track; #endif + + /* for domctl_destroy_domain continuation */ + unsigned long mm_teardown_offset; }; #define INT_ENABLE_OFFSET(v) \ (sizeof(vcpu_info_t) * (v)->vcpu_id + \ diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index 8ac16429b5..d14c4e1e58 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -417,7 +417,7 @@ extern unsigned long totalram_pages; extern int nr_swap_pages; extern void alloc_dom_xen_and_dom_io(void); -extern void mm_teardown(struct domain* d); +extern int mm_teardown(struct domain* d); extern void mm_final_teardown(struct domain* d); extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr); extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);